"""
-*- coding:utf-8 -*-
"""
from itertools import count

from import_manager import *


def get_root_path():
    """获取项目根目录"""
    current = os.getcwd()
    target_dir = "test_api"
    pattern = rf"^[A-Za-z]:[\\\\/]+(?:[^\\\\/]+[\\\\/]+)*{re.escape(target_dir)}[\\\\/]?"
    root_path = re.match(pattern, current, re.IGNORECASE)[0]
    return root_path.replace('\\', '/')


def get_time():
    """获取当前时间"""
    timestamp = int(time.time())
    local_time = time.localtime(timestamp)
    formatted_time = time.strftime("%Y-%m-%d %H-%M-%S", local_time)
    return formatted_time


class Color(Enum):
    FORE = 1
    BACK = 2

    # 设置自定义日志颜色


# log_colors_config = {
#     'DEBUG': 'light_cyan',  # 青
#     'INFO': 'bold_black,bg_green',  # 黑绿
#     'WARNING': 'light_yellow',  # 黄
#     'ERROR': 'bold_black,bg_red',  # 黑红
#     'CRITICAL': 'bold_black,bg_purple'  # 黑紫
# }

log_fore_colors_config = {
    'DEBUG': 'light_cyan',  # 青
    'INFO': 'light_green',  # 绿
    'WARNING': 'light_yellow',  # 黄
    'ERROR': 'light_red',  # 红
    'CRITICAL': 'light_purple'  # 紫
}

log_back_colors_config = {
    'DEBUG': 'bold_black,bg_cyan',  # 黑青
    'INFO': 'bold_black,bg_green',  # 黑绿
    'WARNING': 'bold_black,bg_yellow',  # 黑黄
    'ERROR': 'bold_black,bg_red',  # 黑红
    'CRITICAL': 'bold_black,bg_purple'  # 黑紫
}

# 程序运行根目录 E:/helloworld_python/test_api
ROOT_DIR = get_root_path()
# 日志保存路径
LOG_DIR = os.path.join(ROOT_DIR, "logs")
# 控制台日志级别
STD_LEVEL = logging.NOTSET
# 文件日入日志级别
FILE_LEVEL = logging.NOTSET


class Log:
    def __init__(self, log_dir: str = LOG_DIR, log_color: Color = Color.FORE):
        """
        初始化日志记录器，创建日志文件并管理日志文件大小

        :param log_dir: 日志文件存储的目录路径，默认为LOG_DIR常量定义的路径
        """
        log_path = log_dir + "/log.log"

        # 检查并创建日志目录
        if not os.path.exists(log_dir):
            os.mkdir(log_dir)
            os.chmod(log_dir, 0o777)

        # 检查并创建日志文件
        if not os.path.exists(log_path):
            f = open(log_path, mode='w', encoding='utf-8')
            f.close()
            os.chmod(log_path, 0o777)

        # 如果日志文件超过1MB，将其备份并清空原文件
        if os.path.getsize(log_path) / 1048576 > 1:
            copyfile(log_path, f"{log_dir}/{get_time()}.log")
            with open(log_path, 'w', encoding='utf-8') as f:
                f.truncate()
                f.close()

        # 设置日志格式化器
        self.logger_format = logging.Formatter('%(asctime)s [ %(levelname)s ]: %(message)s')
        self.set_color(log_color)

        # 创建日志记录器实例
        self.logger = logging.getLogger(str(random.random()))
        self.logger.handlers.clear()
        self.logger.setLevel(logging.DEBUG)

        # 配置文件处理器
        self.filehandler = logging.FileHandler(log_path, mode='a')
        self.filehandler.setLevel(FILE_LEVEL)
        self.filehandler.setFormatter(self.logger_format)

        # 配置标准输出处理器
        self.stdouthandler = logging.StreamHandler(sys.stdout)
        self.stdouthandler.setLevel(STD_LEVEL)
        self.stdouthandler.setFormatter(self.c_logger_format)

        # 将处理器添加到日志记录器
        self.logger.addHandler(self.stdouthandler)
        self.logger.addHandler(self.filehandler)

        # 创建多进程锁
        self.__lock = multiprocessing.Lock()

    def __log(self, msg=None, level=logging.INFO):
        if level == logging.DEBUG:
            self.logger.debug(msg)
        elif level == logging.INFO:
            self.logger.info(msg)
        elif level == logging.WARNING:
            self.logger.warning(msg)
        elif level == logging.ERROR:
            self.logger.error(msg)
        elif level == logging.CRITICAL:
            self.logger.critical(msg)

    def __color(self, _color):
        self.c_logger_format = ColoredFormatter(
            fmt='%(log_color)s%(asctime)s 【 %(log_color)s%(levelname)s 】: %(log_color)s%(message)s',
            log_colors=_color,
            reset=True,
            secondary_log_colors={},
            style='%'
        )

    def set_color(self, _color: Color):
        match _color:
            case Color.FORE:
                self.__color(log_fore_colors_config)
            case Color.BACK:
                self.__color(log_back_colors_config)

    def log_show_store(self, msg, level):
        """
        功能：在屏幕显示日志并存储到日志文件中
        :param msg: 日志消息内容
        :param level: 日志级别
        :return: None
        """
        # 获取锁，确保日志写入的线程安全
        self.__lock.acquire()
        # 添加标准输出处理器，用于在屏幕显示日志
        self.logger.addHandler(self.stdouthandler)
        # 添加文件处理器，用于将日志写入文件
        self.logger.addHandler(self.filehandler)
        # 调用内部日志记录方法，记录指定消息和级别的日志
        self.__log(msg=msg, level=level)
        # 释放锁，允许其他线程进行日志操作
        self.__lock.release()

    def log_show(self, msg, level):
        """
        功能：仅在屏幕上显示日志消息
        :param msg: 日志消息内容
        :param level: 日志级别
        """
        # 获取多进程锁，确保日志操作的线程安全
        self.__lock.acquire()
        # 移除文件处理器，避免日志写入文件
        self.logger.removeHandler(self.filehandler)
        # 添加标准输出处理器，使日志仅显示在屏幕上
        self.logger.addHandler(self.stdouthandler)
        # 调用内部日志记录方法，输出指定消息和级别的日志
        self.__log(msg, level=level)
        # 操作完成后，移除标准输出处理器
        self.logger.removeHandler(self.stdouthandler)
        # 重新添加文件处理器，恢复正常的日志记录状态
        self.logger.addHandler(self.filehandler)
        # 释放多进程锁，允许其他进程进行日志操作
        self.__lock.release()

    def log_store(self, msg, level):
        """
        功能：仅将日志消息存储到日志文件中，不在屏幕上显示
        :param msg: 日志消息内容
        :param level: 日志级别
        """
        # 获取多进程锁，确保日志操作的线程安全
        self.__lock.acquire()
        # 移除标准输出处理器，避免日志在屏幕上显示
        self.logger.removeHandler(self.stdouthandler)
        # 添加文件处理器，使日志仅写入到文件中
        self.logger.addHandler(self.filehandler)
        # 调用内部日志记录方法，将指定消息和级别的日志写入文件
        self.__log(msg, level=level)
        # 操作完成后，移除文件处理器
        self.logger.removeHandler(self.filehandler)
        # 重新添加标准输出处理器，恢复正常的日志输出状态
        self.logger.addHandler(self.stdouthandler)
        # 释放多进程锁，允许其他进程进行日志操作
        self.__lock.release()

    def log_wrapper(self, *args):
        """
        功能：记录函数的参数和返回结果的装饰器
        :param args: 装饰器参数
        :return: wrapper 装饰器函数
        """
        # 将传入的参数连接成字符串并存储到日志文件中
        self.log_store(' '.join(args), FILE_LEVEL)

        def wrapper(func):
            # noinspection PyShadowingNames
            def inner(*args, **kwargs):
                # 记录函数调用及其参数
                self.log_store(getattr(func, "__name__") + " call " + str(args) + str(kwargs), 10)
                # 执行被装饰的函数
                ret = func(*args, **kwargs)
                # 记录函数返回值
                self.log_store(getattr(func, "__name__") + " return " + str(ret), 10)
                # 返回函数执行结果
                return ret

            return inner

        return wrapper


if __name__ == '__main__':
    print(f'####################### {__file__} #######################')
    # CRITICAL = 50  # 严重错误
    # FATAL = CRITICAL  # 同CRITICAL
    # ERROR = 40  # 错误
    # WARNING = 30  # 警告
    # WARN = WARNING  # WARNING的简写
    # INFO = 20  # 信息
    # DEBUG = 10  # 调试
    # NOTSET = 0  # 默认级别，不设置级别时，日志将全部记录
    fore_logger = Log(log_color=Color.FORE)
    fore_logger.log_show("log_show", logging.DEBUG)
    fore_logger.log_show("log_show", logging.INFO)
    fore_logger.log_show("log_show", logging.WARNING)
    fore_logger.log_show("log_show", logging.ERROR)
    fore_logger.log_show("log_show", logging.CRITICAL)
    back_logger = Log(log_color=Color.BACK)
    back_logger.log_show("log_show", logging.DEBUG)
    back_logger.log_show("log_show", logging.INFO)
    back_logger.log_show("log_show", logging.WARNING)
    back_logger.log_show("log_show", logging.ERROR)
    back_logger.log_show("log_show", logging.CRITICAL)
